﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Data.OleDb;
using System.Threading.Tasks;

namespace Colonisator.Classes
{
    /// <summary>
    /// Donne l'ensemble du plateau de jeu
    /// </summary>
    public class Plateau
    {
        /// <summary>
        /// Ensemble des éléments (fixes), ou cases, composant le plateau
        /// </summary>
        public List<ElementPlateau> Cases { get; set; }

        /// <summary>
        /// Constructeur de début de partie
        /// </summary>
        public Plateau(string mapName)
        {
            Cases = new List<ElementPlateau>();
            //ChargerMapDepuisExcel(Constantes.SAUVEGARDE_PLATEAU, mapName);
        }

        /// <summary>
        /// Constructeur par défaut
        /// </summary>
        public Plateau()
        {
            Cases = new List<ElementPlateau>();
        }

        /// <summary>
        /// Retourne l'élément plateau suivant, selon la direction voulue.
        /// </summary>
        /// <param name="unElement"></param>
        /// <param name="uneDirection"></param>
        /// <returns></returns>
        public ElementPlateau ElementSuivantSelonDirection(ElementPlateau unElement, PointCardinal uneDirection)
        {
            var element = unElement.AppliquerDiffentiel(uneDirection);
            return LocaliserElementSurPlateau(element);
        }

        public ElementPlateau LocaliserElementSurPlateau(ElementPlateau unElement)
        {
            return this.Cases.Find(x => x.CoordonneeElement.X == unElement.CoordonneeElement.X &&
                x.CoordonneeElement.Y == unElement.CoordonneeElement.Y);
        }

        public ElementPlateau LocaliserElementSurPlateau(Coordonnee uneCoordonnee)
        {
            return this.Cases.Find(x => x.CoordonneeElement.X == uneCoordonnee.X &&
                x.CoordonneeElement.Y == uneCoordonnee.Y);
        }

        /// <summary>
        /// Permet de charger une map Excel sur le plateau en cours
        /// </summary>
        /// <param name="filePath">chemin complet du fichier Excel</param>
        /// <param name="mapName">nom de l'onglet (map)</param>
        public void ChargerMapDepuisExcel(string filePath, string mapName)
        {
            string connectionString = "Provider=Microsoft.ACE.OLEDB.14.0; Data Source =" + filePath;
            connectionString += @"; Extended Properties =""Excel 14.0;HDR=NO;IMEX=1"";";
            OleDbConnection connection = new OleDbConnection(connectionString);
            string cmdText = "SELECT * FROM [" + mapName + "$]";
            OleDbCommand command = new OleDbCommand(cmdText, connection);

            command.Connection.Open();
            OleDbDataReader reader = command.ExecuteReader();

            bool finMap = false;
            bool finLigne = false;

            if (reader.HasRows)
            {
                int ligne = 0;
                while (!finMap)
                {
                    // Traitement d'une ligne
                    reader.Read();
                    finMap = (Convert.ToString(reader[0]) == "f");
                    if (!finMap)
                    {
                        int col = 1;
                        finLigne = false;
                        while (!finLigne)
                        {
                            finLigne = (Convert.ToString(reader[col]) == "z");
                            if (!finLigne)                        
                                AlimenterElementsPlateau(reader, ligne, col);                         
                            col++;
                        }
                    }
                    ligne++;
                }
            }

            reader.Close();
            connection.Close();
        }

        /// <summary>
        /// Alimentation de this.Cases en fonction du texte rencontré
        /// </summary>
        private void AlimenterElementsPlateau(OleDbDataReader reader, int ligne, int col)
        {
            switch (Convert.ToString(reader[col]).ToUpper())
            {
                case Constantes.NON_NAVIGABLE:
                    this.Cases.Add(new ElementPlateau() { CoordonneeElement = new Coordonnee(col, ligne + 1), ElementNavigable = false });
                    break;
                case Constantes.SUNDERCITY:
                    this.Cases.Add(new Sundercity() { CoordonneeElement = new Coordonnee(col, ligne + 1) });
                    break;
                case Constantes.MISSYTOWN:
                    this.Cases.Add(new Missytown() { CoordonneeElement = new Coordonnee(col, ligne + 1) });
                    break;
                case Constantes.PIOFO:
                    this.Cases.Add(new Piofo() { CoordonneeElement = new Coordonnee(col, ligne + 1) });

                    break;
                case Constantes.ILE_NEUTRE_1:
                    if (this.Cases.Find(x => x.GetType() == typeof(IleNeutre1)) == null)
                        this.Cases.Add(new IleNeutre1() { CoordonneeElement = new Coordonnee(col, ligne + 1) });
                    break;
                case Constantes.ILE_NEUTRE_2:
                    if (this.Cases.Find(x => x.GetType() == typeof(IleNeutre2)) == null)
                        this.Cases.Add(new IleNeutre2() { CoordonneeElement = new Coordonnee(col, ligne + 1) });
                    break;
                case Constantes.ILE_NEUTRE_3:
                    if (this.Cases.Find(x => x.GetType() == typeof(IleNeutre3)) == null)
                        this.Cases.Add(new IleNeutre3() { CoordonneeElement = new Coordonnee(col, ligne + 1) });
                    break;
                case Constantes.COLONISABLE_1:
                case Constantes.COLONISABLE_2:
                case Constantes.COLONISABLE_3:
                case Constantes.COLONISABLE_4:
                case Constantes.COLONISABLE_5:
                case Constantes.COLONISABLE_6:
                case Constantes.COLONISABLE_7:
                case Constantes.COLONISABLE_8:
                case Constantes.COLONISABLE_9:
                    this.Cases.Add(new IleColonisable() { CoordonneeElement = new Coordonnee(col, ligne + 1) });
                    break;
                default:
                    this.Cases.Add(new ElementPlateau() { CoordonneeElement = new Coordonnee(col, ligne + 1), ElementNavigable = true });
                    break;
            }
        }
    }
}
